package com.tianyu.inspection.init;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tianyu.inspection.common.Constants;
import com.tianyu.inspection.common.enums.Role;
import com.tianyu.inspection.common.model.JedisModel;
import com.tianyu.inspection.common.model.PackageModel;
import com.tianyu.inspection.common.annotation.Permission;
import com.tianyu.inspection.common.component.AppConstants;
import com.tianyu.inspection.configuration.WebMvcConfig;
import com.tianyu.inspection.entity.BasicInformation;
import com.tianyu.inspection.entity.Pipeline;
import com.tianyu.inspection.mapper.BasicInformationMapper;
import com.tianyu.inspection.mapper.PipelineMapper;
import com.tianyu.inspection.service.telemetry.TelemetryAccessService;
import com.tianyu.inspection.service.websocket.TelemetryQueue;
import io.ocs.model.OcsObject;
import io.ocs.model.OcsSimpleModel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**********************************
 * @Author YSW
 * @Description 程序初始化后执行,【Spring 容器启动完成执行】
 * @Date 2020.12.17 - 15:23
 *
 **********************************/

@Component
@Slf4j
public class ApplicationInit implements CommandLineRunner {

    @Resource
    private JedisModel jedisModel;

    @Resource
    private AppConstants appConstants;

    @Resource
    private TelemetryQueue telemetryQueue;

    @Resource
    private TelemetryAccessService boxClientService;

    @Resource
    private PipelineMapper pipelineMapper;

    @Resource
    private BasicInformationMapper basicInformationMapper;

    @Resource
    private OcsSimpleModel ocsSimpleModel;

    @Override
    public void run(String... args) throws Exception {

        //Jedis客户端初始化连接池
        jedisModel.init();

        //获取接口并缓存
        requestPathRegister();

        log.info("项目初始化完成[ " + System.getProperty("user.dir") + " ], 开启任务线程...");

        //开启遥测定时发送WebSocket线程
        Constants.EXECUTOR.execute(() -> telemetryQueue.start());

        //开启 多项目 云平台多TCP客户端 遥测下发、存储线程
        Constants.EXECUTOR.execute(() -> boxClientService.start());

        //dev();
    }

    @SneakyThrows
    private void dev() {
        final List<Pipeline> pipelines = pipelineMapper.selectList(Wrappers.<Pipeline>lambdaQuery());
        System.out.println(pipelines.size());
        for (Pipeline pipeline : pipelines) {
            if (pipeline.getType() == 0) {
                final JSONArray objects = JSONArray.of();
                final String pointsUrl = pipeline.getPointsUrl();
                final OcsObject object = ocsSimpleModel.getObject(pointsUrl);
                final InputStream inputStream = object.getInputStream();
                final byte[] bytes = new byte[Math.toIntExact(object.getContentLength())];
                inputStream.read(bytes);
                if (object.getContentLength() > 0) {

                    try {
                        final com.tianyu.inspection.common.protobuf.Pipeline.DataList dataList = com.tianyu.inspection.common.protobuf.Pipeline.DataList.parseFrom(bytes);
                        System.out.println(ocsSimpleModel.getObjectUrl(pointsUrl));
                        final List<com.tianyu.inspection.common.protobuf.Pipeline.Point> pointList = dataList.getPointList();
                        for (com.tianyu.inspection.common.protobuf.Pipeline.Point point : pointList) {
                            objects.add(JSONObject.of("lng", point.getLng(), "lat", point.getLat(), "alt", point.getAlt()));
                        }

                        System.out.println(pointList);
                    } catch (Exception e) {
                        basicInformationMapper.insert(BasicInformation.builder()
                                .id(pipeline.getId())
                                .parentId(pipeline.getParentId())
                                .folder(false)
                                .jsonContent(JSONObject.of())
                                .mapLayerType(2)
                                .typeDefId(83)
                                .name(pipeline.getName())
                                .state(1)
                                .projectId(pipeline.getProjectId())
                                .build());
                        continue;
                    }
                }
                basicInformationMapper.insert(BasicInformation.builder()
                        .id(pipeline.getId())
                        .parentId(pipeline.getParentId())
                        .folder(false)
                        .jsonContent(JSONObject.of("description", pipeline.getDescription(),
                                "name", pipeline.getName(),
                                "lineStyle", JSONObject.of("width", pipeline.getWide(), "color", pipeline.getColor()),
                                "linePoints", objects))
                        .mapLayerType(2)
                        .typeDefId(83)
                        .name(pipeline.getName())
                        .state(0)
                        .projectId(pipeline.getProjectId())
                        .build());
            } else {
                basicInformationMapper.insert(BasicInformation.builder()
                        .id(pipeline.getId())
                        .parentId(pipeline.getParentId())
                        .folder(true)
                        .mapLayerType(2)
                        .name(pipeline.getName())
                        .state(0)
                        .projectId(pipeline.getProjectId())
                        .build());
            }
        }
    }

    public static final Map<String, Integer> REQUEST_PATH_PERMISSION = new LinkedHashMap<>(300);

    public void requestPathRegister() {
        //TODO 注册所有权限化接口
        String name = WebMvcConfig.class.getPackage().getName();
        String packageName = name.substring(0, name.lastIndexOf(".")) + ".controller";
        List<String> classNames = PackageModel.getClassName(packageName, true);
        if (classNames != null) {
            for (String className : classNames) {
                try {
                    Class<?> controllerClass = Class.forName(className);
                    RequestMapping requestMapping = controllerClass.getAnnotation(RequestMapping.class);
                    for (Method method : controllerClass.getDeclaredMethods()) {
                        Permission permission = method.getAnnotation(Permission.class);
                        GetMapping getMapping = method.getAnnotation(GetMapping.class);
                        PostMapping postMapping = method.getAnnotation(PostMapping.class);
                        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
                        PutMapping putMapping = method.getAnnotation(PutMapping.class);
                        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
                        if (Objects.nonNull(getMapping)) {
                            permissionSort(requestMapping, permission, getMapping.value());
                            continue;
                        }
                        if (Objects.nonNull(postMapping)) {
                            permissionSort(requestMapping, permission, postMapping.value());
                            continue;
                        }
                        if (Objects.nonNull(patchMapping)) {
                            permissionSort(requestMapping, permission, patchMapping.value());
                            continue;
                        }
                        if (Objects.nonNull(putMapping)) {
                            permissionSort(requestMapping, permission, putMapping.value());
                            continue;
                        }
                        if (Objects.nonNull(deleteMapping)) {
                            permissionSort(requestMapping, permission, deleteMapping.value());
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            REQUEST_PATH_PERMISSION.forEach(((path, role) -> {
                String roleName = "";
                if (role == 1) {
                    roleName = Role.ROLE_SUPER_ADMIN.getMessage();
                }
                if (role == 2) {
                    roleName = Role.ROLE_COMPANY_ADMIN.getMessage();
                }
                if (role == 3) {
                    roleName = Role.ROLE_COMPANY_COMMON.getMessage();
                }
                if (role == 4) {
                    roleName = Role.ROLE_PATROL.getMessage();
                }
                log.debug(path);
            }));
            log.debug("接口数量 -> [" + REQUEST_PATH_PERMISSION.size() + "]");
        }
    }

    private void permissionSort(RequestMapping requestMapping, Permission permission, String[] value) {
        String realPath;
        if (Objects.nonNull(requestMapping)) {
            realPath = requestMapping.value()[0] + value[0];
        } else {
            realPath = value[0];
        }
        if (Objects.nonNull(permission)) {
            REQUEST_PATH_PERMISSION.put(realPath, permission.value());
        }
    }

    @Scheduled(cron = "0 0 2 * * ?")
    public void fileStatisticalAnalysisScheduled() {

    }
}
